home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / oleo-1_4.lha / oleo-1.4 / input.c < prev    next >
C/C++ Source or Header  |  1993-05-14  |  10KB  |  428 lines

  1. /*    Copyright (C) 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17.  
  18. #include "global.h"
  19. #include "input.h"
  20. #include "cmd.h"
  21. #include "window.h"
  22. #include "io-abstract.h"
  23.  
  24.  
  25. /* In the functions below, we only ever deal with one input_view at a 
  26.  * time.  By convention, call a pointer to it THIS_IV and use these
  27.  * macros: 
  28.  */
  29. #define Redraw_needed         (this_iv->redraw_needed)
  30. #define Prompt_metric         (this_iv->prompt_metric)
  31. #define Input_metric         (this_iv->input_metric)
  32. #define Keymap_prompt         (this_iv->keymap_prompt)
  33. #define Expanded_keymap_prompt     (this_iv->expanded_keymap_prompt)
  34. #define Prompt_wid         (this_iv->prompt_wid)
  35. #define Must_fix_input         (this_iv->must_fix_input)
  36. #define Input_area         (this_iv->input_area)
  37. #define Prompt             (this_iv->prompt)
  38. #define Visibility_begin     (this_iv->visibility_begin)
  39. #define Visibility_end         (this_iv->visibility_end)
  40. #define Current_info        (this_iv->current_info)
  41. #define Info_pos        (this_iv->info_pos)
  42. #define Info_redraw_needed    (this_iv->info_redraw_needed)
  43. #define Vis_wid            (this_iv->vis_wid)
  44. #define Input_cursor         (this_iv->input_cursor)
  45.  
  46.  
  47.  
  48. #define Max(A,B)  ((A) < (B) ? (B) : (A))
  49. #define Min(A,B)  ((A) > (B) ? (B) : (A))
  50.  
  51.  
  52. /* Decide if a keymap prompt should be displayed.  If so, 
  53.  * return the prompt, else 0.
  54.  */
  55.  
  56. #ifdef __STDC__
  57. static char * 
  58. desired_keymap_prompt (struct input_view * this_iv)
  59. #else
  60. static char * 
  61. desired_keymap_prompt (this_iv)
  62.      struct input_view * this_iv;
  63. #endif
  64. {
  65.   int map = cur_keymap;
  66.   if (the_cmd_frame->cmd && (the_cmd_arg.style == &keyseq_style))
  67.     map = the_cmd_arg.val.key.cmd.code;
  68.   return ((map >= 0) ? map_prompts[map] : 0);
  69. }
  70.  
  71.  
  72.  
  73.  
  74. /* In WID columns, find the first char in STR that can
  75.  * be displayed while still leaving POS visible.  METRIC
  76.  * converts str->cols.
  77.  */
  78.  
  79. #ifdef __STDC__
  80. static int
  81. find_vis_begin (int * wid_used, int wid,
  82.         char * str, int pos, text_measure metric)
  83. #else
  84. static int
  85. find_vis_begin (wid_used, wid, str, pos, metric)
  86.      int * wid_used;
  87.      int wid;
  88.      char * str;
  89.      int pos;
  90.      text_measure metric;
  91. #endif
  92. {
  93.   int used;            /* How many cols allocated? */
  94.   if (str[pos])
  95.     used = metric (&str[pos], 1);
  96.   else
  97.     /* POS could be just after the end of STR, in which case pretend
  98.      * that the character there is a SPC. 
  99.      */
  100.     used = metric (" ", 1);
  101.  
  102.   while (pos && (used < wid))
  103.     {
  104.       int next;
  105.       next = metric (&str[pos - 1], 1);
  106.       if (used + next > wid)
  107.     break;
  108.       else
  109.     {
  110.       --pos;
  111.       used += next;
  112.     }
  113.     }
  114.   if (wid_used)
  115.     *wid_used = used;
  116.   return pos;
  117. }
  118.  
  119.  
  120.  
  121. /* Find the last visible character...  -1 if none are vis. */
  122.  
  123. #ifdef __STDC__
  124. static int
  125. find_vis_end (int * wid_used, int wid, char * str, int start, text_measure
  126.           metric) 
  127. #else
  128. static int
  129. find_vis_end (wid_used, wid, str, start, metric)
  130.      int * wid_used;
  131.      int wid;
  132.      char * str;
  133.      int start;
  134.      text_measure metric;
  135. #endif
  136. {
  137.   int used = metric (&str[start], 1);    /* How many cols allocated? */
  138.   int pos = start;
  139.   int max = strlen (str) - 1;
  140.  
  141.   while ((pos < max) && (used < wid))
  142.     {
  143.       int next;
  144.       next = metric (&str[pos + 1], 1);
  145.       if (used + next > wid)
  146.     break;
  147.       else
  148.     {
  149.       ++pos;
  150.       used += next;
  151.     }
  152.     }
  153.   if (wid_used)
  154.     *wid_used = used;
  155.   return pos;
  156. }
  157.  
  158. #ifdef __STDC__
  159. static void
  160. set_vis_wid (struct input_view * this_iv)
  161. #else
  162. static void
  163. set_vis_wid (this_iv)
  164.      struct input_view * this_iv;
  165. #endif
  166. {
  167.   Vis_wid = (Input_metric (Input_area->buf + Visibility_begin,
  168.                  Visibility_end - Visibility_begin)
  169.            + ((Input_cursor > Visibility_end)
  170.           ? Input_metric (" ", 1)
  171.           : 0));
  172. }
  173.  
  174.  
  175. /* This recomputes the input area parameters of an input_view, attempting to 
  176.  * center the cursor. 
  177.  */
  178.  
  179. #ifdef __STDC__
  180. static void
  181. iv_reset_input (struct input_view * this_iv)
  182. #else
  183. void
  184. static iv_reset_input (this_iv)
  185.      struct input_view * this_iv;
  186. #endif
  187. {
  188.   char * km = desired_keymap_prompt (this_iv);
  189.   if (km && (km == Keymap_prompt))
  190.     return;
  191.   Redraw_needed = FULL_REDRAW;
  192.   Keymap_prompt = km;
  193.   if (km)
  194.     {
  195.       /* A keymap prompt should be displayed. */
  196.       Expanded_keymap_prompt = expand_prompt (Keymap_prompt);
  197.       Prompt_wid = Prompt_metric (Expanded_keymap_prompt,
  198.                   strlen(Expanded_keymap_prompt));
  199.       Must_fix_input = 1;
  200.       Visibility_begin = Visibility_end = 0;
  201.       Input_area = 0;
  202.       Vis_wid = Input_metric (" ", 1);
  203.       Prompt = 0;
  204.       Input_cursor = 0;
  205.     }
  206.   else
  207.     {
  208.       if (Expanded_keymap_prompt)
  209.     {
  210.       ck_free (Expanded_keymap_prompt);
  211.       Expanded_keymap_prompt = 0;
  212.     }
  213.       if (!the_cmd_frame->cmd || the_cmd_arg.is_set || !the_cmd_arg.do_prompt)
  214.     {
  215.       Prompt_wid = 0;
  216.       Must_fix_input = 0;
  217.       Input_area = 0;
  218.       Vis_wid = 0;
  219.       Prompt = 0;
  220.       Visibility_begin = Visibility_end = 0;
  221.       Input_cursor = 0;
  222.     }
  223.       else
  224.     {
  225.       Prompt_wid = Prompt_metric (the_cmd_arg.expanded_prompt,
  226.                        strlen (the_cmd_arg.expanded_prompt));
  227.       Must_fix_input = 0;
  228.       Input_area = &the_cmd_arg.text;
  229.       Prompt = the_cmd_arg.expanded_prompt;
  230.  
  231.       if ((scr_cols - Prompt_wid) < Input_metric ("M", 1))
  232.         Prompt += find_vis_begin (&Prompt_wid,
  233.                       scr_cols - Input_metric("M", 1),
  234.                       Prompt, strlen(Prompt) - 1,
  235.                       Prompt_metric);
  236.       
  237.       {
  238.         int wid_avail = scr_cols - Prompt_wid;
  239.         Visibility_begin =
  240.           find_vis_begin (0, wid_avail / 2, Input_area->buf,
  241.                   the_cmd_arg.cursor, Input_metric);
  242.         Visibility_end =
  243.           find_vis_end (0, wid_avail,
  244.                 Input_area->buf, Visibility_begin,
  245.                 Input_metric); 
  246.       }
  247.  
  248.       Input_cursor = the_cmd_arg.cursor;
  249.       set_vis_wid (this_iv);
  250.     }
  251.     }
  252. }
  253.  
  254.  
  255.  
  256.  
  257.  
  258. /* This is called strategicly from the command loop and whenever
  259.  * the input area is changed by beginning a complex command.
  260.  * It may do nothing, though if the input area appeas to have changed
  261.  * it will recompute its appearence.
  262.  *
  263.  * now it also updates the info_fields of the input view.
  264.  */
  265.  
  266. #ifdef __STDC__
  267. void
  268. iv_fix_input (struct input_view * this_iv)
  269. #else
  270. void
  271. iv_fix_input (this_iv)
  272.      struct input_view * this_iv;
  273. #endif
  274. {
  275.   char * km_prompt = desired_keymap_prompt (this_iv);
  276.  
  277.   if (Keymap_prompt && (Keymap_prompt == km_prompt))
  278.  
  279.     Must_fix_input = 1;        /* Do nothing, keymap prompt has precedence */
  280.  
  281.   else if (Must_fix_input
  282.        || (Keymap_prompt != km_prompt)
  283.        || ((the_cmd_frame->cmd
  284.         && (the_cmd_arg.do_prompt && !the_cmd_arg.is_set))
  285.            ? ((Input_area != &the_cmd_arg.text)
  286.           || (Prompt != the_cmd_arg.expanded_prompt)
  287.           || (Input_cursor != the_cmd_arg.cursor))
  288.            : (Input_area || Prompt_wid)))
  289.     iv_reset_input (this_iv);
  290.  
  291.   if (the_cmd_frame->cmd
  292.       && ((the_cmd_arg.prompt_info != Current_info)
  293.       || (the_cmd_arg.info_line != Info_pos)))
  294.     {
  295.       Current_info = the_cmd_arg.prompt_info;
  296.       Info_pos = the_cmd_arg.info_line;
  297.       Info_redraw_needed = 1;
  298.     }
  299.   else if (Current_info
  300.        && (!the_cmd_frame->cmd || !the_cmd_arg.prompt_info))
  301.     {
  302.       Current_info = 0;
  303.       io_repaint ();
  304.     }
  305.        
  306. }
  307.  
  308.  
  309. /* Incremental updates:
  310.  * For simple edits it is not necessary to redraw the entire line.
  311.  * These schedule incremental updating.
  312.  */
  313.  
  314.  
  315. #ifdef __STDC__
  316. void
  317. iv_move_cursor (struct input_view * this_iv)
  318. #else
  319. void
  320. iv_move_cursor (this_iv)
  321.      struct input_view * this_iv;
  322. #endif
  323. {
  324.   if (   Must_fix_input
  325.       || (Visibility_begin > the_cmd_arg.cursor)
  326.       || (   ((Visibility_end + 1) < the_cmd_arg.cursor)
  327.       || (((Visibility_end + 1) == the_cmd_arg.cursor)
  328.           && ((Vis_wid + Prompt_wid) < scr_cols))))
  329.  
  330.     Must_fix_input = 1;
  331.   else if (Redraw_needed != FULL_REDRAW)
  332.     {
  333.       if (   (Redraw_needed == NO_REDRAW)
  334.       || ((Redraw_needed > Input_cursor)
  335.           && (Redraw_needed > the_cmd_arg.cursor)))
  336.     {
  337.       Input_cursor = the_cmd_arg.cursor;
  338.       set_vis_wid (this_iv);
  339.     }
  340.       else
  341.     {
  342.       Redraw_needed = Min (Input_cursor, the_cmd_arg.cursor);
  343.       set_vis_wid (this_iv);
  344.     }
  345.     }
  346. }
  347.  
  348. #ifdef __STDC__
  349. void
  350. iv_erase (struct input_view * this_iv, int len)
  351. #else
  352. void
  353. iv_erase (this_iv, len)
  354.      struct input_view * this_iv;
  355.      int len;
  356. #endif
  357. {
  358.   if (Must_fix_input
  359.       || (the_cmd_arg.cursor <= Visibility_begin))
  360.     {
  361.       Must_fix_input = 1;
  362.       return;
  363.     }
  364.   else if (Redraw_needed != FULL_REDRAW)
  365.     {
  366.       if ((Redraw_needed == NO_REDRAW) || (Redraw_needed > the_cmd_arg.cursor))
  367.     {
  368.       Redraw_needed = the_cmd_arg.cursor;
  369.       Visibility_end = find_vis_end (0, scr_cols - Prompt_wid,
  370.                      Input_area->buf, Visibility_begin,
  371.                      Input_metric);
  372.       Input_cursor = the_cmd_arg.cursor;
  373.     }
  374.       else
  375.     Redraw_needed = the_cmd_arg.cursor;
  376.       set_vis_wid (this_iv);
  377.     }
  378. }
  379.  
  380.  
  381. #ifdef __STDC__
  382. void
  383. iv_insert (struct input_view * this_iv, int len)
  384. #else
  385. void
  386. iv_insert (this_iv, len)
  387.      struct input_view * this_iv;
  388.      int len;
  389. #endif
  390. {
  391.   if (!Must_fix_input)
  392.     {
  393.       int new_end;
  394.       int cursor_past_end = (Input_cursor + len == strlen (Input_area->buf));
  395.       
  396.       new_end = find_vis_end (0, scr_cols - Prompt_wid,
  397.                   Input_area->buf, Visibility_begin,
  398.                   Input_metric);
  399.       
  400.       if ((new_end + cursor_past_end) < (Input_cursor + len))
  401.     Must_fix_input = 1;
  402.       else
  403.     {
  404.       if (   (Redraw_needed != FULL_REDRAW)
  405.           && ((Redraw_needed == NO_REDRAW) || (Redraw_needed > Input_cursor)))
  406.         Redraw_needed = Input_cursor;
  407.       Input_cursor += len;
  408.       Visibility_end = new_end;
  409.       set_vis_wid (this_iv);
  410.     }
  411.     }
  412. }
  413.        
  414. #ifdef __STDC__
  415. void
  416. iv_over (struct input_view * this_iv, int len)
  417. #else
  418. void
  419. iv_over (this_iv, len)
  420.      struct input_view * this_iv;
  421.      int len;
  422. #endif
  423. {
  424.   iv_insert (this_iv, len);
  425. }
  426.  
  427.  
  428.